#include "bmp280.h"
BMP280_TYPE BMP280_Data;
#define CONST_PF 0.1902630958	                                               //(1/5.25588f) Pressure factor
#define FIX_TEMP 25				                                               // Fixed Temperature. ASL is a function of pressure and temperature, 
																				//but as the temperature changes so much (blow a little towards the flie and watch it drop 5 degrees) it corrupts the ASL estimates.
								                                               // TLDR: Adjusting for temp changes does more harm than good.

//产生IIC起始信号
void BMP_IIC_Start(void)
{
	SDA_OUT();                                                                 //sda线输出
	IIC_SDA=1;	  	  
	IIC_SCL=1;
	delay_us(4);
 	IIC_SDA=0;                                                                 //START:when CLK is high,DATA change form high to low 
	delay_us(4);
	IIC_SCL=0;                                                                 //钳住I2C总线，准备发送或接收数据 
}	  
//产生IIC停止信号
void BMP_IIC_Stop(void)
{
	SDA_OUT();                                                                 //sda线输出
	IIC_SCL=0;
	IIC_SDA=0;                                                                 //STOP:when CLK is high DATA change form low to high
 	delay_us(4);
	IIC_SCL=1; 
	IIC_SDA=1;                                                                 //发送I2C总线结束信号
	delay_us(4);							   	
}
//等待应答信号到来
//返回值：1，接收应答失败
//        0，接收应答成功
u8 BMP_IIC_Wait_Ack(void)
{
	u8 ucErrTime=0;
	SDA_IN();                                                                  //SDA设置为输入  
	IIC_SDA=1;delay_us(1);	   
	IIC_SCL=1;delay_us(1);	 
	while(READ_SDA)
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			BMP_IIC_Stop();
			return 1;
		}
	}
	IIC_SCL=0;                                                                 //时钟输出0 	   
	return 0;  
} 
//产生ACK应答
void BMP_IIC_Ack(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=0;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}

//不产生ACK应答		    
void BMP_IIC_NAck(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=1;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}					 

//IIC发送一个字节
//返回从机有无应答
//1，有应答
//0，无应答			  
void BMP_IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
	SDA_OUT(); 	    
    IIC_SCL=0;                                                                 //拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
        IIC_SDA=(txd&0x80)>>7;
        txd<<=1; 	  
		delay_us(2);                                                           //对TEA5767这三个延时都是必须的
		IIC_SCL=1;
		delay_us(2); 
		IIC_SCL=0;	
		delay_us(2);
    }	 
} 	    
//读1个字节，ack=1时，发送ACK，ack=0，发送nACK   
u8 BMP_IIC_Read_Byte(unsigned char ack)
{
	unsigned char i,receive=0;
	SDA_IN();                                                                  //SDA设置为输入
    for(i=0;i<8;i++ )
	{
        IIC_SCL=0; 
        delay_us(2);
		IIC_SCL=1;
        receive<<=1;
        if(READ_SDA)receive++;   
		delay_us(1); 
    }					 
    if (!ack)
        BMP_IIC_NAck();                                                            //发送nACK
    else
        BMP_IIC_Ack();                                                             //发送ACK   
    return receive;
}

//从指定地址读出一个数据
//ReadAddr:开始读数的地址  
//返回值  :读到的数据
u8 BMP_iicDevReadByte(u8 devaddr,u8 addr)
{				  
	u8 temp=0;		  	    																 
	BMP_IIC_Start();  
	BMP_IIC_Send_Byte(devaddr);                                                    //发送器件写命令 	   
	BMP_IIC_Wait_Ack(); 
	BMP_IIC_Send_Byte(addr);                                                       //发送低地址
	BMP_IIC_Wait_Ack();	

	BMP_IIC_Start();  	 	   
	BMP_IIC_Send_Byte(devaddr|1);                                                  //发送器件读命令			   
	BMP_IIC_Wait_Ack();	 
	temp=BMP_IIC_Read_Byte(0);			   
	BMP_IIC_Stop();                                                                //产生一个停止条件	    
	return temp;
}

//连续读多个字节
//addr:起始地址
//rbuf:读数据缓存
//len:数据长度
void BMP_iicDevRead(u8 devaddr,u8 addr,u8 len,u8 *rbuf)
{
	int i=0;
	BMP_IIC_Start();  
	BMP_IIC_Send_Byte(devaddr);  
	BMP_IIC_Wait_Ack();	
	BMP_IIC_Send_Byte(addr);                                                       //地址自增  
	BMP_IIC_Wait_Ack();	

	BMP_IIC_Start();  	
	BMP_IIC_Send_Byte(devaddr|1);  	
	BMP_IIC_Wait_Ack();	
	for(i=0; i<len; i++)
	{
		if(i==len-1)
		{
			rbuf[i]=BMP_IIC_Read_Byte(0);                                          //最后一个字节不应答
		}
		else
			rbuf[i]=BMP_IIC_Read_Byte(1);
	}
	BMP_IIC_Stop( );	
}

//从指定地址写入一个数据
//WriteAddr :写入数据的目的地址    
//DataToWrite:要写入的数据
void BMP_iicDevWriteByte(u8 devaddr,u8 addr,u8 data)
{				   	  	    																 
	BMP_IIC_Start();  
	BMP_IIC_Send_Byte(devaddr);                                                    //发送器件写命令 	 
	BMP_IIC_Wait_Ack();	   
	BMP_IIC_Send_Byte(addr);                                                       //发送低地址
	BMP_IIC_Wait_Ack(); 	 										  		   
	BMP_IIC_Send_Byte(data);                                                       //发送字节							   
	BMP_IIC_Wait_Ack();  		    	   
	BMP_IIC_Stop();		                                                           //产生一个停止条件 	 
}

short BMP280_ReadTwo(uint8_t addr)
{
	uint8_t msb, lsb;
	short temp = 0;
	lsb = BMP_iicDevReadByte(BMP280_ADDR, addr);
	msb = BMP_iicDevReadByte(BMP280_ADDR, addr+1);
	temp = (short)msb<<8;
	temp |= (short)lsb;
	return temp;

}

long BMP280_ReadThree(uint8_t addr)
{
	uint8_t msb, lsb, xlsb;
	long temp = 0;
	msb = BMP_iicDevReadByte(BMP280_ADDR,addr);
	lsb = BMP_iicDevReadByte(BMP280_ADDR, addr+1);
	xlsb = BMP_iicDevReadByte(BMP280_ADDR, addr+2);
    temp = (long)(((unsigned long)msb << 12)|((unsigned long)lsb << 4)|((unsigned long)xlsb >> 4));
	return temp;
}

//连续写多个字节
//addr:起始地址
//wbuf:写数据缓存
//len:数据的长度
void BMP_iicDevWrite(u8 devaddr,u8 addr,u8 len,u8 *wbuf)
{
	int i=0;
	BMP_IIC_Start();  
	BMP_IIC_Send_Byte(devaddr);  	
	BMP_IIC_Wait_Ack();	
	BMP_IIC_Send_Byte(addr);  //地址自增
	BMP_IIC_Wait_Ack();	
	for(i=0; i<len; i++)
	{
		BMP_IIC_Send_Byte(wbuf[i]);  
		BMP_IIC_Wait_Ack();		
	}
	BMP_IIC_Stop( );	
}
static uint8_t bmp280ID=0;
static bool isInit=false;

static void presssureFilter(float* in,float* out);

bool bmp280Init(void)
{	
    if (isInit)
        return true;
	                                                           /*初始化I2C*/
    delay_ms(20);
	
	bmp280ID=BMP_iicDevReadByte(BMP280_ADDR,BMP280_CHIP_ID);	                   /* 读取bmp280 ID*/
	
	if(bmp280ID==BMP280_DEFAULT_CHIP_ID)
		printf("BMP280 ID IS: 0x%X\n",bmp280ID);
    else
        return false;
	BMP_iicDevWriteByte(BMP280_ADDR, BMP280_RST_REG, 0xB6);
    /* 读取校准数据 */
	BMP280_Data.dig_T1 = BMP280_ReadTwo(0x88);
	BMP280_Data.dig_T2 = BMP280_ReadTwo(0x8A);
	BMP280_Data.dig_T3 = BMP280_ReadTwo(0x8C);
	BMP280_Data.dig_P1 = BMP280_ReadTwo(0x8E);
	BMP280_Data.dig_P2 = BMP280_ReadTwo(0x90);
	BMP280_Data.dig_P3 = BMP280_ReadTwo(0x92);
	BMP280_Data.dig_P4 = BMP280_ReadTwo(0x94);
	BMP280_Data.dig_P5 = BMP280_ReadTwo(0x96);
	BMP280_Data.dig_P6 = BMP280_ReadTwo(0x98);
	BMP280_Data.dig_P7 = BMP280_ReadTwo(0x9A);
	BMP280_Data.dig_P8 = BMP280_ReadTwo(0x9C);
	BMP280_Data.dig_P9 = BMP280_ReadTwo(0x9E);
	
//	printf("BMP280 Calibrate Registor Are: \r\n");
//	for(i=0;i<24;i++)
//		printf("Registor %2d: 0x%X\n",i,p[i]);
    isInit=true;
    return true;
}


#define FILTER_NUM	5
#define FILTER_A	0.1f

/*限幅平均滤波法*/
static void presssureFilter(float* in,float* out)
{	
	static u8 i=0;
	static float filter_buf[FILTER_NUM]={0.0};
	double filter_sum=0.0;
	u8 cnt=0;	
	float deta;

	if(filter_buf[i]==0.0f)
	{
		filter_buf[i]=*in;
		*out=*in;
		if(++i>=FILTER_NUM)	
			i=0;
	} 
	else 
	{
		if(i)
			deta=*in-filter_buf[i-1];
		else 
			deta=*in-filter_buf[FILTER_NUM-1];
		
		if(fabs(deta)<FILTER_A)
		{
			filter_buf[i]=*in;
			if(++i>=FILTER_NUM)	
				i=0;
		}
		for(cnt=0;cnt<FILTER_NUM;cnt++)
		{
			filter_sum+=filter_buf[cnt];
		}
		*out=filter_sum /FILTER_NUM;
	}
}

void BMP280_GetValue(void)
{
	long adc_T, adc_P;
	long var1, var2, t_fine,  P;

	adc_T = BMP280_ReadThree(BMP280_TEMPERATURE_MSB_REG);
	adc_P = BMP280_ReadTwo(BMP280_PRESSURE_MSB_REG);
	var1 = ((((float)adc_T) / 16384.0f) - (((float)BMP280_Data.dig_T1) / 1024.0f)) * ((float)BMP280_Data.dig_T2);
    var2 = (((((float)adc_T) / 131072.0f) - (((float)BMP280_Data.dig_T1) / 8192.0f)) *
            (((float)adc_T) / 131072.0f) - (((float)BMP280_Data.dig_T1) / 8192.0f)) * ((float)BMP280_Data.dig_T3);

	BMP280_Data.Temperature = (var1+var2)/5120.0;
 
	var1 = ((double)t_fine / 2.0f) - 64000.0;
	var2 = var1 * var1 * ((double)BMP280_Data.dig_P6) / 32768.0f;
	var2 = var2 + var1 * ((double)BMP280_Data.dig_P5) * 2.0f;
	var2 = (var2 / 4.0f) + (((double)BMP280_Data.dig_P4)*65536.0);
	var1 = (((double)BMP280_Data.dig_P3)* var1 * var1 / 524288.0 + ((double)BMP280_Data.dig_P2)*var1) / 524288.0;
	var1 = (1.0+var1/32768.0)*((double)BMP280_Data.dig_P1);
	if (var1 == 0.0f)
	{
		P = 0;
	}
	else 
	{
		P = 1048576.0 - (double)adc_P;
		P = (P - (var2 / 4096.0)) * 6250.0 / var1;
		var1 = ((double)BMP280_Data.dig_P9)* P *P / 2147483648.0;
		var2 = P * ((double)BMP280_Data.dig_P8) / 32768.0;
		BMP280_Data.Pressure = P+(var1+var2+((double)BMP280_Data.dig_P7))/16.0;
	}
}	



//压力值转换为气压值 单位：pha(帕)
// Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits).
// Output value of "24674867" represents 24674867/256 = 96386.2 Pa = 963.862 hPa
void BMP280_PressureTOPha(BMP280_TYPE *BMP280_Data)
{
	BMP280_Data->Pha_before = BMP280_Data->Pressure / 256.0f;
	presssureFilter(&BMP280_Data->Pha_before, &BMP280_Data->Pha_after);
}

//温度值转换为摄氏度
void BMP280_TempToDegree(BMP280_TYPE *BMP280_Data)
{
	BMP280_Data->degree = BMP280_Data->Temperature / 100.f;
}
/**
*  @func:BMP280_PhaToAltitude
*  @brief:将气压值（帕）海拔数据转换为高度，单位：米
*  @param:
*  @return:
**/
uint32_t BMP280_PhaToAltitude(BMP280_TYPE BMP280_Data)
{
	if (BMP280_Data.Pha_after > 0)
    {
        BMP280_Data.Height = ((pow((1015.7f/ BMP280_Data.Pha_after),CONST_PF)-1.0f)*(FIX_TEMP+273.15f))/ 0.0065f;
		return BMP280_Data.Height;
    }
    else
    {
        return 0;
    }
}
